﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows.Forms;
using DiscoveryLogic.Common.Utilities;
using DiscoveryLogic.DataViz.NetworkDiagram.Dedup;
using DiscoveryLogic.DataViz.NetworkDiagram.FieldComparers;
using DiscoveryLogic.DataViz.NetworkDiagram.NetworkData;
using DiscoveryLogic.DataViz.NetworkDiagram.Rules;
using DiscoveryLogic.WindowsUserControl.Codes;
using EntityType=DiscoveryLogic.DataViz.NetworkDiagram.NetworkData.EntityType;

namespace DiscoveryLogic.DataViz.NetworkDiagram.LinkerControls
{
    /// <summary>
    /// 
    /// </summary>
    public partial class EntityRelationRuleDefinition : Form
    {
        #region events 
        /// <summary>
        /// 
        /// </summary>
        /// <param name="rule"></param>
        public delegate void OnRelationRuleDefined(EntityRelationRule rule);

        public event OnRelationRuleDefined RelationRuleDefined;
        #endregion

        #region fields
        private EntityRelationRule _Rule;
        private readonly Network _Network;
        private DataTable _NetworkData;
        private int _ActiveRowIndex = -1;
        #endregion

        #region init
        /// <summary>
        /// 
        /// </summary>
        /// <param name="network"></param>
        public EntityRelationRuleDefinition(Network network)
        {
            this._Network = network;
            this._Rule = new EntityRelationRule();
            InitializeComponent();
        }

        private void EntityRelationRuleDefinition_Load(object sender, EventArgs e)
        {
            this.PopulateEntityTypes();
            this.PopulateDbProviders();
            this.PopulateDistanceCalculators();
            this.PopulateDedupCalcs();
            this._NetworkData = this.ReadNetworkData();
            this.wizard1.SelectedPage = this.introductionPage1;
            this.SelectComboValue(this.cbo_SrcEntityTypes, this._Network.EntityType.ToString());
        }

        private void PopulateEntityTypes()
        {
            this.cbo_SrcEntityTypes.Items.Clear();
            this.cbo_TgtEntityType.Items.Clear();
            for(int i=0;i<=3;i++)
            {
                EntityType entityType = (EntityType) i;
                this.cbo_SrcEntityTypes.Items.Add(entityType.ToString());
                this.cbo_TgtEntityType.Items.Add(entityType.ToString());
            }
        }

        private void SelectComboValue(ComboBox combo, string value)
        {
            if(combo.Items.Count>0 && !string.IsNullOrEmpty(value))
            {
                for(int i=0;i<combo.Items.Count;i++)
                {
                    if(combo.Items[i].ToString()==value)
                    {
                        combo.SelectedIndex = i;
                        break;
                    }
                }
            }
        }

        private void PopulateDbProviders()
        {
            this.cbo_DbProvider.Items.Clear();
            for (int i = 0; i <= 1;i++)
            {
                DataProviderType dbProvider = (DataProviderType) i;
                this.cbo_DbProvider.Items.Add(dbProvider.ToString());
            }
        }

        private void PopulateDistanceCalculators()
        {
            this.cbo_DistanceCalc.Items.Clear();
            Assembly assembly = typeof(ILinkDistanceCalculator).Assembly;
            Type[] types = assembly.GetTypes();
            foreach(Type type in types)
            {
                if(type.GetInterface(typeof(IEntityLinker).FullName)!= null)
                {
                    this.cbo_DistanceCalc.Items.Add(type.FullName);
                }
            }
        }

        private void PopulateDedupCalcs()
        {
            this.cbo_Dedup2.Items.Clear();
            Assembly assembly = typeof(IDedupCalculator).Assembly;
            Type[] types = assembly.GetTypes();
            foreach (Type type in types)
            {
                if (type.GetInterface(typeof(IDedupCalculator).FullName) != null)
                {
                    this.cbo_Dedup2.Items.Add(type.FullName);
                }
            }
        }

        private DataTable ReadNetworkData()
        {
            DataTable dtNetData=new DataTable();
            List<LinkDataObject> links=new List<LinkDataObject>();
            Network.ReadData(this._Network.NetworkName, ref dtNetData, ref links);
            return dtNetData;
        }
        #endregion

        #region input bindings
        private void cbo_SrcEntityTypes_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (this.cbo_SrcEntityTypes.SelectedIndex >= 0)
            {
                this.dv_InputBindings.Rows.Clear();
                EntityType entityType = (EntityType)this.cbo_SrcEntityTypes.SelectedIndex;
                PropertyInfo[] props = null;
                switch (entityType)
                {
                    case EntityType.Publications:
                        props = typeof(PublicationDO).GetProperties();
                        break;
                    case EntityType.Organization:
                        props = typeof(ExternalOrgDO).GetProperties();
                        break;
                    case EntityType.Persons:
                        props = typeof(PersonDO).GetProperties();
                        break;
                    case EntityType.Project:
                        props = typeof(GrantDO).GetProperties();
                        break;
                }

                this.cbo_SrcIDField.Items.Clear();
                this.cbo_SrcNameField.Items.Clear();
                if (props != null && props.Length > 0)
                {
                    foreach (PropertyInfo prop in props)
                    {
                        this.cbo_SrcIDField.Items.Add(prop.Name);
                        this.cbo_SrcNameField.Items.Add(prop.Name);
                        DataGridViewRow dr = new DataGridViewRow();
                        DataGridViewTextBoxCell cellPropName = new DataGridViewTextBoxCell();
                        cellPropName.Value = prop.Name;
                        dr.Cells.Add(cellPropName);

                        DataGridViewComboBoxCell cellSrcFields = new DataGridViewComboBoxCell();
                        if (this._NetworkData != null && this._NetworkData.Columns.Count > 0)
                        {
                            foreach (DataColumn col in this._NetworkData.Columns)
                            {
                                cellSrcFields.Items.Add(col.ColumnName);
                            }
                        }
                        dr.Cells.Add(cellSrcFields);
                        this.dv_InputBindings.Rows.Add(dr);
                    }
                }
            }
        }

        private void wiz_SrcData_BeforeMoveNext(object sender, CancelEventArgs e)
        {
            if (this.cbo_SrcEntityTypes.SelectedIndex < 0)
                e.Cancel = true;
            else if(this.cbo_SrcIDField.SelectedIndex<0)
                e.Cancel = true;
            else if (this.cbo_SrcNameField.SelectedIndex < 0)
                e.Cancel = true;
            else
            {
                this._Rule.FieldNameMappings = new Dictionary<string, string>();
                foreach (DataGridViewRow dr in this.dv_InputBindings.Rows)
                {
                    if (!dr.IsNewRow && dr.Cells[0].Value != null && dr.Cells[1].Value != null)
                    {
                        string entityFieldName = dr.Cells[0].Value.ToString();
                        string srcFieldName = dr.Cells[1].Value.ToString();
                        this._Rule.FieldNameMappings.Add(entityFieldName, srcFieldName);
                    }
                }
                EntityType entityType = (EntityType)this.cbo_SrcEntityTypes.SelectedIndex;
                switch (entityType)
                {
                    case EntityType.Publications:
                        this._Rule.SrcEntityType = typeof(PublicationDO);
                        break;
                    case EntityType.Organization:
                        this._Rule.SrcEntityType = typeof(ExternalOrgDO);
                        break;
                    case EntityType.Persons:
                        this._Rule.SrcEntityType = typeof(PersonDO);
                        break;
                    case EntityType.Project:
                        this._Rule.SrcEntityType = typeof(GrantDO);
                        break;
                }

                this._Rule.SrcEntityIDField = this.cbo_SrcIDField.Text;
                this._Rule.SrcEntityNameField = this.cbo_SrcNameField.Text;
            }
        }
        #endregion

        #region relation data
        private void wiz_RelationData_BeforeMoveNext(object sender, CancelEventArgs e)
        {
            if (string.IsNullOrEmpty(this.txt_ConnStr.Text) ||
                string.IsNullOrEmpty(this.rt_Sql.Text) ||
                this.cbo_DbProvider.SelectedIndex < 0)
            {
                e.Cancel = true;
            }
            else
            {
                this._Rule.DbProvider = (DataProviderType)this.cbo_DbProvider.SelectedIndex;
                this._Rule.ConnStr = this.txt_ConnStr.Text;
                this._Rule.Sql = this.rt_Sql.Text;
            }

        }
        #endregion

        #region sql parameter bindings
        private void wiz_InputBinding_BeforeDisplay(object sender, EventArgs e)
        {
            this.dv_ParameterBinding.Rows.Clear();
            Regex paramRegex = new Regex(@"@([^\s,=\)]+)", RegexOptions.IgnoreCase);
            Match paramMatch = paramRegex.Match(this._Rule.Sql);
            while (paramMatch.Success)
            {
                string paramName = paramMatch.Groups[1].Value;
                DataGridViewRow dr = new DataGridViewRow();

                DataGridViewTextBoxCell cellParamName = new DataGridViewTextBoxCell();
                cellParamName.Value = paramName;
                dr.Cells.Add(cellParamName);

                DataGridViewComboBoxCell cellSrcFields = new DataGridViewComboBoxCell();
                PropertyInfo[] srcProps = this._Rule.SrcEntityType.GetProperties();
                if(srcProps !=null && srcProps.Length>0)
                {
                    foreach (PropertyInfo prop in srcProps)
                    {
                        cellSrcFields.Items.Add(prop.Name);
                    }
                }
                dr.Cells.Add(cellSrcFields);

                DataGridViewComboBoxCell cellDataType = new DataGridViewComboBoxCell();
                foreach (SqlDbType dbType in Enum.GetValues(typeof(SqlDbType)))
                {
                    cellDataType.Items.Add(dbType.ToString());
                }
                dr.Cells.Add(cellDataType);

                DataGridViewImageCell cellTransform = new DataGridViewImageCell();
                cellTransform.Value = imageList1.Images[0];
                dr.Cells.Add(cellTransform);

                DataGridViewTextBoxCell cellTransformCode = new DataGridViewTextBoxCell();
                cellTransformCode.Value = string.Empty;
                dr.Cells.Add(cellTransformCode);

                this.dv_ParameterBinding.Rows.Add(dr);

                paramMatch = paramMatch.NextMatch();
            }
        }

        private void wiz_InputBinding_BeforeMoveNext(object sender, CancelEventArgs e)
        {
            this._Rule.SqlParameters=new Dictionary<string, string>();
            this._Rule.ParameterTypes = new Dictionary<string, SqlDbType>();
            this._Rule.FieldTransformations = new Dictionary<string, string>();
            foreach (DataGridViewRow dr in this.dv_ParameterBinding.Rows)
            {
                if (!dr.IsNewRow && dr.Cells[0].Value != null &&
                    dr.Cells[1].Value != null)
                {
                    string paramName = dr.Cells[0].Value.ToString();
                    string propName = dr.Cells[1].Value.ToString();
                    this._Rule.SqlParameters.Add(paramName, propName);

                    SqlDbType dbType = SqlDbType.VarChar;
                    if (dr.Cells[2].Value != null)
                    {
                        dbType = (SqlDbType)Enum.Parse(
                                                 typeof(SqlDbType),
                                                 dr.Cells[2].Value.ToString());
                    }
                    this._Rule.ParameterTypes.Add(paramName, dbType);

                    string code = dr.Cells[4].Value.ToString();
                    if (!string.IsNullOrEmpty(code))
                    {
                        this._Rule.FieldTransformations.Add(propName, code);
                    }
                }
            }
        }

        private void dv_ParameterBinding_CellClick(object sender, DataGridViewCellEventArgs e)
        {
            if (e.RowIndex >= 0 && e.ColumnIndex == 3 &&
                !this.dv_ParameterBinding.Rows[e.RowIndex].IsNewRow)
            {
                DataGridViewRow dr = this.dv_ParameterBinding.Rows[e.RowIndex];
                SqlDbType dbType = SqlDbType.VarChar;
                if (dr.Cells[2].Value != null)
                {
                    dbType = (SqlDbType)Enum.Parse(typeof(SqlDbType), dr.Cells[2].Value.ToString());
                }
                Type sysType = FieldDataType.ToSystemType(dbType);
                string code = dr.Cells[4].Value.ToString();
                string methodSig = string.Format(
                    "public {0} TransformFieldValue({0} fieldValue) ",
                    sysType.Name);
                CodeEditor editor = new CodeEditor(methodSig + " {");
                editor.Code = code;
                this._ActiveRowIndex = e.RowIndex;
                editor.CodeUpdated += new CodeEditor.OnCodeUpdated(editor_CodeUpdated);
                editor.Show(this);
            }
        }

        void editor_CodeUpdated(string code)
        {
            if (this._ActiveRowIndex >= 0 && this.dv_ParameterBinding.Rows.Count > this._ActiveRowIndex)
            {
                if (string.IsNullOrEmpty(code))
                {
                    this.dv_ParameterBinding.Rows[this._ActiveRowIndex].Cells[3].Value =
                        this.imageList1.Images[0];
                    this.dv_ParameterBinding.Rows[this._ActiveRowIndex].Cells[4].Value = string.Empty;
                }
                else
                {
                    this.dv_ParameterBinding.Rows[this._ActiveRowIndex].Cells[3].Value =
                        this.imageList1.Images[1];
                    this.dv_ParameterBinding.Rows[this._ActiveRowIndex].Cells[4].Value = code;
                }
            }
        }

        private void dv_ParameterBinding_CellEndEdit(object sender, DataGridViewCellEventArgs e)
        {
            if(e.RowIndex>=0 && e.RowIndex<this.dv_ParameterBinding.Rows.Count && 
                e.ColumnIndex==1)
            {
                string propName = this.dv_ParameterBinding.Rows[e.RowIndex].Cells[1].Value.ToString();
                PropertyInfo prop = this._Rule.SrcEntityType.GetProperty(propName);
                if(prop !=null)
                {
                    SqlDbType dbType = SqlDbTypeUtil.ToSqlDbType(prop.PropertyType);
                    this.dv_ParameterBinding.Rows[e.RowIndex].Cells[2].Value = dbType.ToString();
                }
            }
        }
        #endregion

        #region output bindings
        private void cbo_TgtEntityType_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (this.cbo_TgtEntityType.SelectedIndex < 0)
                return;
            if (this._NetworkData == null || this._NetworkData.Rows.Count == 0)
            {
                MessageBox.Show("network data is empty");
                return;
            }

            try
            {
                EntityType entityType = (EntityType) this.cbo_TgtEntityType.SelectedIndex;
                PropertyInfo[] props = null;
                switch (entityType)
                {
                    case EntityType.Publications:
                        props = typeof (PublicationDO).GetProperties();
                        break;
                    case EntityType.Organization:
                        props = typeof (ExternalOrgDO).GetProperties();
                        break;
                    case EntityType.Persons:
                        props = typeof (PersonDO).GetProperties();
                        break;
                    case EntityType.Project:
                        props = typeof (GrantDO).GetProperties();
                        break;
                }

                this.cbo_TgtIDField.Items.Clear();
                this.cbo_TgtNameField.Items.Clear();
                foreach(PropertyInfo prop in props)
                {
                    this.cbo_TgtIDField.Items.Add(prop.Name);
                    this.cbo_TgtNameField.Items.Add(prop.Name);
                }

                string sql = this._Rule.Sql;
                Regex paramRegex = new Regex(@"@([^\s=,\)]+)", RegexOptions.IgnoreCase);
                Match paramMatch = paramRegex.Match(this._Rule.Sql);
                while (paramMatch.Success)
                {
                    string paramName = paramMatch.Groups[1].Value;
                    if (this._Rule.SqlParameters.ContainsKey(paramName))
                    {
                        string propName = this._Rule.SqlParameters[paramName];
                        string srcFieldName = this._Rule.FieldNameMappings[propName];
                        SqlDbType dbType = this._Rule.ParameterTypes[paramName];
                        SimpleDataType dbType2 = SimpleDataTypeUtil.ToSimpleDataType(dbType);
                        object fieldValue = this._NetworkData.Rows[0][srcFieldName];
                        fieldValue = SimpleDataTypeUtil.ReadDbValue(dbType2, fieldValue);

                        if (fieldValue == null)
                        {
                            sql = sql.Replace("@" + paramName, "null");
                        }
                        else if (this._Rule.FieldTransformations.ContainsKey(srcFieldName))
                        {
                            object transformedValue = fieldValue;
                            string sqlValue = FieldDataType.ToMssqlDataValue(dbType, transformedValue.ToString());
                            sql = sql.Replace("@" + paramName, sqlValue);
                        }
                        else
                        {
                            string sqlValue = FieldDataType.ToMssqlDataValue(dbType, fieldValue.ToString());
                            sql = sql.Replace("@" + paramName, sqlValue);
                        }
                    }

                    paramMatch = paramMatch.NextMatch();
                }

                this.dv_OutputBinding.Rows.Clear();
                TableColumn[] cols = DbUtil.GetTableColumns(
                    this._Rule.DbProvider,
                    this._Rule.ConnStr, sql);
                if (cols != null && props != null)
                {
                    foreach (TableColumn col in cols)
                    {
                        DataGridViewRow dr = new DataGridViewRow();
                        DataGridViewTextBoxCell cellColName = new DataGridViewTextBoxCell();
                        cellColName.Value = col.ColumnName;
                        dr.Cells.Add(cellColName);
                        DataGridViewComboBoxCell cellPropName = new DataGridViewComboBoxCell();
                        foreach (PropertyInfo prop in props)
                        {
                            cellPropName.Items.Add(prop.Name);
                        }
                        dr.Cells.Add(cellPropName);
                        this.dv_OutputBinding.Rows.Add(dr);
                    }
                }
            }
            catch(Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        private void wiz_OutputBinding_BeforeMoveNext(object sender, CancelEventArgs e)
        {
            if (this.cbo_TgtEntityType.SelectedIndex < 0)
                e.Cancel = true;
            else if(this.cbo_TgtIDField.SelectedIndex<0)
                e.Cancel = true;
            else if (this.cbo_TgtNameField.SelectedIndex < 0)
                e.Cancel = true;
            else
            {
                EntityType entityType = (EntityType)this.cbo_TgtEntityType.SelectedIndex;
                switch (entityType)
                {
                    case EntityType.Publications:
                        this._Rule.TgtEntityType = typeof(PublicationDO);
                        break;
                    case EntityType.Organization:
                        this._Rule.TgtEntityType = typeof(ExternalOrgDO);
                        break;
                    case EntityType.Persons:
                        this._Rule.TgtEntityType = typeof(PersonDO);
                        break;
                    case EntityType.Project:
                        this._Rule.TgtEntityType = typeof(GrantDO);
                        break;
                }
                this._Rule.TgtEntityIDField = this.cbo_TgtIDField.Text;
                this._Rule.TgtEntityNameField = this.cbo_TgtNameField.Text;
                this._Rule.OutputFieldNameMappings = new Dictionary<string, string>();
                foreach (DataGridViewRow dr in this.dv_OutputBinding.Rows)
                {
                    if (!dr.IsNewRow && dr.Cells[0].Value != null && dr.Cells[1].Value != null)
                    {
                        string colName = dr.Cells[0].Value.ToString();
                        string entityFieldName = dr.Cells[1].Value.ToString();
                        this._Rule.OutputFieldNameMappings.Add(colName, entityFieldName);
                    }
                }
            }
        }
        #endregion

        #region distance calc
        private void cbo_DistanceCalc_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (this.cbo_DistanceCalc.SelectedIndex >= 0)
            {
                this.dv_DistanceArgs.Rows.Clear();
                string typeName = this.cbo_DistanceCalc.SelectedItem.ToString();
                Assembly assembly = typeof(IEntityLinker).Assembly;
                Type type = assembly.GetType(typeName);
                IEntityLinker calc = (IEntityLinker)Activator.CreateInstance(type);
                List<string> args = calc.ArgNames;
                if (args != null && args.Count > 0)
                {
                    foreach (string argName in args)
                    {
                        DataGridViewRow dr = new DataGridViewRow();
                        DataGridViewTextBoxCell cellArgName = new DataGridViewTextBoxCell();
                        cellArgName.Value = argName;
                        dr.Cells.Add(cellArgName);
                        DataGridViewComboBoxCell cellEntityFields1 = new DataGridViewComboBoxCell();
                        PropertyInfo[] props = this._Rule.SrcEntityType.GetProperties();
                        if (props != null && props.Length > 0)
                        {
                            foreach (PropertyInfo prop in props)
                            {
                                cellEntityFields1.Items.Add(prop.Name);
                            }
                        }
                        dr.Cells.Add(cellEntityFields1);

                        DataGridViewComboBoxCell cellEntityFields = new DataGridViewComboBoxCell();
                        PropertyInfo[] props2 = this._Rule.TgtEntityType.GetProperties();
                        if (props2 != null && props2.Length > 0)
                        {
                            foreach (PropertyInfo prop in props2)
                            {
                                cellEntityFields.Items.Add(prop.Name);
                            }
                        }
                        dr.Cells.Add(cellEntityFields);

                        this.dv_DistanceArgs.Rows.Add(dr);
                    }
                }
            }
        }

        private void wiz_CalcSetting_BeforeMoveNext(object sender, CancelEventArgs e)
        {
            if (this.cbo_DistanceCalc.SelectedIndex < 0)
                e.Cancel = true;
            else
            {
                Assembly assembly = typeof (IEntityLinker).Assembly;
                this._Rule.EntityLinkerType = assembly.GetType(this.cbo_DistanceCalc.Text);
                this._Rule.LinkCalcArgumentMappings = new Dictionary<string, ArgumentFieldBinding>();
                foreach (DataGridViewRow dr in this.dv_DistanceArgs.Rows)
                {
                    if (!dr.IsNewRow && dr.Cells[0].Value != null)
                    {
                        string argName = dr.Cells[0].Value.ToString();
                        ArgumentFieldBinding argBinding = new ArgumentFieldBinding();
                        if (dr.Cells[1].Value != null && !string.IsNullOrEmpty(dr.Cells[1].Value.ToString()))
                        {
                            argBinding.FromSrcEntity = true;
                            argBinding.FromTgtEntity = false;
                            argBinding.PropertyName = dr.Cells[1].Value.ToString();
                        }
                        else if (dr.Cells[2].Value != null && !string.IsNullOrEmpty(dr.Cells[2].Value.ToString()))
                        {
                            argBinding.FromSrcEntity = false;
                            argBinding.FromTgtEntity = true;
                            argBinding.PropertyName = dr.Cells[2].Value.ToString();
                        }
                        this._Rule.LinkCalcArgumentMappings.Add(argName, argBinding);
                    }
                }

                this._Rule.LinkDistanceThreshold = (double)this.num_DistanceThreshold.Value;
                this._Rule.HopDampFactor = (double)this.num_HopDampFactor.Value;
                this._Rule.AllowLoopBack = this.ck_Loopback.Checked;
            }
        }
        #endregion

        #region dedup
        private void wiz_Dedup_BeforeDisplay(object sender, EventArgs e)
        {
            this.dv_DedupFields2.Rows.Clear();
            Assembly assembly = typeof(IAttributeComparer).Assembly;
            List<string> fieldComparerTypes = new List<string>();
            Type[] types = assembly.GetTypes();
            foreach (Type type in types)
            {
                if (type.GetInterface(typeof(IAttributeComparer).FullName) != null)
                {
                    fieldComparerTypes.Add(type.FullName);
                }
            }

            PropertyInfo[] props2 = this._Rule.TgtEntityType.GetProperties();
            if(props2 !=null && props2.Length>0)
            {
                foreach(PropertyInfo prop in props2)
                {
                    DataGridViewRow dr1 = new DataGridViewRow();

                    DataGridViewCheckBoxCell cellSelect1 = new DataGridViewCheckBoxCell();
                    cellSelect1.Value = false;
                    dr1.Cells.Add(cellSelect1);

                    DataGridViewTextBoxCell cellFieldName1 = new DataGridViewTextBoxCell();
                    cellFieldName1.Value = prop.Name;
                    dr1.Cells.Add(cellFieldName1);

                    DataGridViewCheckBoxCell cellAffiliation1 = new DataGridViewCheckBoxCell();
                    cellAffiliation1.Value = false;
                    dr1.Cells.Add(cellAffiliation1);

                    DataGridViewComboBoxCell cellComparer1 = new DataGridViewComboBoxCell();
                    if (fieldComparerTypes != null && fieldComparerTypes.Count > 0)
                    {
                        foreach (string fieldComparerType in fieldComparerTypes)
                        {
                            cellComparer1.Items.Add(fieldComparerType);
                        }
                    }
                    dr1.Cells.Add(cellComparer1);

                    DataGridViewTextBoxCell cellWeight1 = new DataGridViewTextBoxCell();
                    cellWeight1.Value = "1.0";
                    dr1.Cells.Add(cellWeight1);

                    DataGridViewTextBoxCell cellPenalty1 = new DataGridViewTextBoxCell();
                    cellPenalty1.Value = "0.0";
                    dr1.Cells.Add(cellPenalty1);

                    this.dv_DedupFields2.Rows.Add(dr1);
                }
            }
        }

        private void wiz_Dedup_BeforeMoveNext(object sender, CancelEventArgs e)
        {
            if(this.cbo_Dedup2.SelectedIndex<0)
            {
                e.Cancel = true;
            }
            else
            {
                Assembly assembly = typeof (IDedupCalculator).Assembly;
                this._Rule.DedupCalculatorType = assembly.GetType(this.cbo_Dedup2.Text);
                this._Rule.DedupNativeComparers = new Dictionary<string, string>();
                this._Rule.DedupAssociativeComparers = new Dictionary<string, string>();
                this._Rule.DedupFieldWeights=new Dictionary<string, double>();
                this._Rule.DedupPenalties = new Dictionary<string, double>();
                this._Rule.DedupSimilarityThreshold = (double) this.num_DedupCollapseThreshold2.Value;
                this._Rule.DedupAssociationThreshold = (double) this.num_DedupAssocThreshold2.Value;
                foreach(DataGridViewRow dr in this.dv_DedupFields2.Rows)
                {
                    if(!dr.IsNewRow && dr.Cells[0].Value !=null && dr.Cells[1].Value !=null && 
                        dr.Cells[3].Value !=null)
                    {
                        bool selected = bool.Parse(dr.Cells[0].Value.ToString());
                        if(selected)
                        {
                            string fieldName = dr.Cells[1].Value.ToString();
                            bool isAssociative = bool.Parse(dr.Cells[2].Value.ToString());
                            string comparerTypeName = dr.Cells[3].Value.ToString();
                            double weight = double.Parse(dr.Cells[4].Value.ToString());
                            double penalty = double.Parse(dr.Cells[5].Value.ToString());
                            if(isAssociative)
                                this._Rule.DedupAssociativeComparers.Add(fieldName,comparerTypeName);
                            else 
                                this._Rule.DedupNativeComparers.Add(fieldName, comparerTypeName);
                            this._Rule.DedupFieldWeights.Add(fieldName,weight);
                            this._Rule.DedupPenalties.Add(fieldName,penalty);
                        }
                    }
                }
            }
        }
        #endregion

        #region finish
        private void wizard1_Finish(object sender, EventArgs e)
        {
            this._Rule.RuleName = this.txt_RuleName.Text;
            if(this.RelationRuleDefined !=null)
            {
                this.RelationRuleDefined(this._Rule);
            }
        }
        #endregion

        #region cancel
        private void wizard1_Cancel(object sender, EventArgs e)
        {
            this.Close();
        }
        #endregion

        private void wiz_CalcSetting_BeforeDisplay(object sender, EventArgs e)
        {

        }

        private void wiz_OutputBinding_BeforeDisplay(object sender, EventArgs e)
        {

        }

        private void wiz_SrcData_BeforeDisplay(object sender, EventArgs e)
        {

        }

    }
}
